﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection;
using System.Threading;
using Wise.Util;

namespace Wise.Application.Entity
{
    /// <summary>
    /// 实体类基类
    /// </summary>
    [Serializable]
    public abstract class BaseEntity
    {

        static BaseEntity()
        {

        }

        /// <summary>
        /// 
        /// </summary>
        public BaseEntity()
        {

        }


        /// <summary>
        /// 新增调用
        /// </summary>
        public virtual void Create()
        {
            IsShouldEncrypted = true;
            if (this is IIdEntity)
            {
                (this as IIdEntity).Id = Guid.NewGuid().ToString();
            }
            if (this is ICreatedByUserEntity)
            {
                ICreatedByUserEntity entity = this as ICreatedByUserEntity;
                entity.CreateDate = DateTime.Now;
                var _CurrentOperator = GetCurrentUserInfo.Current;
                entity.CreateUserId = _CurrentOperator.UserId;
                entity.CreateUserName = _CurrentOperator.UserName;
            }
            if (this is IEnabledEntity)
            {
                (this as IEnabledEntity).Enabled = 1;
            }
        }

        /// <summary>
        /// 新增调用
        /// </summary>
        public virtual void CreateApp()
        {
            if (this is IIdEntity)
            {
                (this as IIdEntity).Id = Guid.NewGuid().ToString();
            }
            if (this is ICreatedByUserEntity)
            {
                ICreatedByUserEntity entity = this as ICreatedByUserEntity;
                entity.CreateDate = DateTime.Now;
                var _CurrentOperator = GetCurrentUserInfo.Current;
                entity.CreateUserId = _CurrentOperator.UserId;
                entity.CreateUserName = _CurrentOperator.UserName;
            }
            if (this is IEnabledEntity)
            {
                (this as IEnabledEntity).Enabled = 1;
            }
        }
        /// <summary>
        /// 编辑调用
        /// </summary>
        /// <param name="keyValue">主键值</param>
        public virtual void Modify(string keyValue)
        {
            IsShouldEncrypted = true;

            if (this is IModifyedByUserEntity)
            {
                IModifyedByUserEntity entity = this as IModifyedByUserEntity;
                entity.ModifyDate = DateTime.Now;
                var _CurrentOperator = GetCurrentUserInfo.Current;
                entity.ModifyUserId = _CurrentOperator.UserId;
                entity.ModifyUserName = _CurrentOperator.UserName;
            }
        }
        /// <summary>
        /// 删除调用
        /// </summary>
        /// <param name="keyValue">主键值</param>
        public virtual void Remove(string keyValue)
        {
            //IsShouldEncrypted = true;
        }

        /// <summary>
        /// 获取可能加密也可能是解密的数据。
        /// 由IsShouldEncrypted控制是加密的还是解密的数据，默认是解密的数据！
        /// </summary>
        /// <param name="key">要获取的字段</param>
        /// <returns></returns>
        public virtual string Get_EncrptSome_Value(string key)
        {
            Tuple<string, string> myValue = (Tuple<string, string>)_Values[key];
            if (myValue == null)
            {
                return string.Empty;
            }
            if (IsShouldEncrypted)
            {
                return myValue.Item2;
            }
            else
            {
                return myValue.Item1;
            }
        }

        /// <summary>
        /// 设置可能加密也可能是解密的数据。
        /// 由IsEncryptedInput控制输入值是否已加密，默认是解密的数据
        /// </summary>
        /// <param name="key">要设置的字段</param>
        /// <param name="value">要设置的值</param>
        /// <remarks>不应该使用IsShouldEncrypted控制输入，因为它是控制输出的。</remarks>
        public virtual void Set_EncrptSome_Value(string key, string value)
        {
            if (string.IsNullOrEmpty(value) || string.Equals("&nbsp;", value))
            {
                _Values[key] = new Tuple<string, string>(string.Empty, string.Empty);
            }
            else if (IsEncryptedInput)
            {
                try
                {
                    _Values[key] = new Tuple<string, string>(SecurityHelper.Decrypt(value), value);
                }
                catch (Exception)
                {
                    _Values[key] = new Tuple<string, string>(value, SecurityHelper.Encrypt(value));
                }
            }
            else
            {
                _Values[key] = new Tuple<string, string>(value, SecurityHelper.Encrypt(value));
            }
        }

        [NotMapped, NonSerialized]
        protected readonly NameObjectCollection _Values = new NameObjectCollection();


        /// <summary>
        /// 获取字符串值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        protected virtual string getStringValue(string key)
        {
            Object obj = _Values[key];
            return obj == null ? string.Empty : (String)obj;
        }


        /// <summary>
        /// NotMapped NonSerialized 输出数据是否应该加密
        /// 默认值：应该直接输出/false
        /// </summary>
        [NotMapped]
        public bool IsShouldEncrypted
        {
            get { return _IsShouldEncrypted; }
            set { _IsShouldEncrypted = value; }
        }

        bool _IsShouldEncrypted = false;


        /// <summary>
        /// NotMapped NonSerialized 输入数据是否已加密
        /// 默认值：DEFAULT_IsEncryptedInput 或 输入的是未加密的数据/false
        /// 注意：对整个对象而言要求，所有实用加密属性的字段数据都是已加密的方式存储！
        /// 否则，将在读取数据时抛出异常。
        /// 读我：可以使用 NHI.Sync.Tools 对数据库字段 批量加密
        /// </summary>
        [NotMapped]
        public bool IsEncryptedInput
        {
            get
            {
                return _IsEncryptedInput == null ?
                  Get_DEFAULT_IsEncryptedInput(this.GetType())
                  : _IsEncryptedInput.Value;
            }
            set { _IsEncryptedInput = value; }
        }

        bool? _IsEncryptedInput = null;
        /// <summary>
        /// 获取实体类型默认输入值是否已加密
        /// </summary>
        /// <typeparam name="TEntity">要获取的实体类型</typeparam>
        /// <returns></returns>
        public static bool Get_DEFAULT_IsEncryptedInput<TEntity>()
            where TEntity : BaseEntity
        {
            return Get_DEFAULT_IsEncryptedInput(typeof(TEntity));
        }

        /// <summary>
        /// 获取实体类型默认输入值是否已加密
        /// </summary>
        /// <param name="key">要获取的实体类型</param>
        /// <returns></returns>
        public static bool Get_DEFAULT_IsEncryptedInput(Type key)
        {
            if (DEFAULT_IsEncryptedInput == null)
                DEFAULT_IsEncryptedInput = new Dictionary<Type, bool>();
            return DEFAULT_IsEncryptedInput.ContainsKey(key) ? DEFAULT_IsEncryptedInput[key] : false;
        }

        /// <summary>
        /// 设置实体类型默认输入值是否已加密
        /// </summary>
        /// <typeparam name="TEntity">要设置的实体类型</typeparam>
        /// <param name="value">要设置的值</param>
        /// <returns></returns>
        public static void Set_DEFAULT_IsEncryptedInput<TEntity>(bool value)
            where TEntity : BaseEntity
        {
            Set_DEFAULT_IsEncryptedInput(typeof(TEntity), value);
        }

        /// <summary>
        /// 设置实体类型默认输入值是否已加密
        /// </summary>
        /// <param name="key">要获取的实体类型</param>
        /// <param name="value">要设置的值</param>
        /// <returns></returns>
        public static void Set_DEFAULT_IsEncryptedInput(Type key, bool value)
        {
            if (DEFAULT_IsEncryptedInput == null)
                DEFAULT_IsEncryptedInput = new Dictionary<Type, bool>();
            if (!DEFAULT_IsEncryptedInput.ContainsKey(key))
                DEFAULT_IsEncryptedInput.Add(key, false);
            DEFAULT_IsEncryptedInput[key] = value;
        }

        /// <summary>
        /// NotMapped NonSerialized 设置默认值：输入数据是否已加密
        /// 注意：它是线程依赖的，每个Request有且至少有一个独立值，不受其他Request影响。
        /// 如果你在使用多线程，那么，它会有对每个线程有唯一独立值！
        /// 默认：false
        /// </summary>
        /// <remarks>
        /// 为什么既在每个对象内有 IsEncryptedInput，还要有针对线程的 DEFAULT_IsEncryptedInput？
        /// 1.从数据库读取数据时，来不及为每个对象赋值 IsEncryptedInput ，未赋值IsEncryptedInput的必然会引发异常
        /// 2.从客户端以实体类获取数据时，来不及为每个对象赋值 IsEncryptedInput ，未赋值IsEncryptedInput的可能引发异常
        /// 为什么默认是false？
        /// 1.国际上，默认值通常被设定为false
        /// 2.从客户端获取数据时，默认是false
        /// </remarks>
        [NotMapped, ThreadStatic, NonSerialized]
        public static Dictionary<Type, bool> DEFAULT_IsEncryptedInput = new Dictionary<Type, bool>();
    }

    /// <summary>
    /// 键值对
    /// </summary>
    [Serializable]
    public class NameObjectCollection : NameObjectCollectionBase
    {
        /// Creates an empty collection.
        public NameObjectCollection()
        {
        }

        /// Adds elements from an IDictionary into the new collection.
        public NameObjectCollection(IDictionary d, Boolean bReadOnly)
        {
            foreach (DictionaryEntry de in d)
            {
                this.BaseAdd((String)de.Key, de.Value);
            }
            this.IsReadOnly = bReadOnly;
        }

        /// Gets a key-and-value pair (DictionaryEntry) using an index.
        public DictionaryEntry this[int index]
        {
            get
            {
                return (new DictionaryEntry(
                    this.BaseGetKey(index), this.BaseGet(index)));
            }
        }

        /// Gets or sets the value associated with the specified key.
        public Object this[String key]
        {
            get
            {
                return (this.BaseGet(key));
            }
            set
            {
                this.BaseSet(key, value);
            }
        }

        /// Gets a String array that contains all the keys in the collection.
        public String[] AllKeys
        {
            get
            {
                return (this.BaseGetAllKeys());
            }
        }

        /// Gets an Object array that contains all the values in the collection.
        public Array AllValues
        {
            get
            {
                return (this.BaseGetAllValues());
            }
        }

        /// Gets a String array that contains all the values in the collection.
        public String[] AllStringValues
        {
            get
            {
                return ((String[])this.BaseGetAllValues(typeof(string)));
            }
        }

        /// Gets a value indicating if the collection contains keys that are not null.
        public Boolean HasKeys
        {
            get
            {
                return (this.BaseHasKeys());
            }
        }

        /// Adds an entry to the collection.
        public void Add(String key, Object value)
        {
            this.BaseAdd(key, value);
        }

        /// Removes an entry with the specified key from the collection.
        public void Remove(String key)
        {
            this.BaseRemove(key);
        }

        /// Removes an entry in the specified index from the collection.
        public void Remove(int index)
        {
            this.BaseRemoveAt(index);
        }

        /// Clears all the elements in the collection.
        public void Clear()
        {
            this.BaseClear();
        }
    }

    /// <summary>
    /// Id实体接口
    /// </summary>
    public interface IIdEntity
    {

        /// <summary>
        /// 主键
        /// </summary>
        string Id { get; set; }
    }

    /// <summary>
    /// 主键名称实体
    /// </summary>
    public interface IIdNameEntity : IIdEntity
    {
        /// <summary>
        /// 名称
        /// </summary>
        string Name { get; set; }

        /// <summary>
        /// 简称
        /// </summary>
        string ShortName { get; set; }
    }

    /// <summary>
    /// 可禁用的实体接口
    /// </summary>
    public interface IEnabledEntity
    {
        /// <summary>
        /// 是否启用
        /// </summary>
        /// <remarks>
        /// 必须使用可空类型，否则，从客户端接收数据时，会因为默认值0，而变成禁用！
        /// </remarks>
        int? Enabled { get; set; }
    }

    /// <summary>
    /// 与创建人相关的实体接口
    /// </summary>
    public interface ICreatedByUserEntity
    {

        /// <summary>
        /// 创建时间
        /// </summary>
        DateTime? CreateDate { get; set; }
        /// <summary>
        /// 创建用户的Id
        /// </summary>
        string CreateUserId { get; set; }
        /// <summary>
        /// 创建人
        /// </summary>
        string CreateUserName { get; set; }

    }


    /// <summary>
    /// 与创建人相关的实体接口
    /// </summary>
    public interface IModifyedByUserEntity
    {

        /// <summary>
        /// 修改时间
        /// </summary>
        DateTime? ModifyDate { get; set; }
        /// <summary>
        /// 修改用户的Id
        /// </summary>
        string ModifyUserId { get; set; }
        /// <summary>
        /// 修改人
        /// </summary>
        string ModifyUserName { get; set; }

    }

    /// <summary>
    /// 获取当前用户信息
    /// </summary>
    public class GetCurrentUserInfo
    {
        static Type ThatType = null;
        static PropertyInfo ProviderProperty = null;
        static MethodInfo CurrentMethod = null;

        /// <summary>
        /// 获取当前用户的委托
        /// </summary>
        public static Func<GetCurrentUserInfo> GetCurrentUserDelegate = null;

        [ThreadStatic]
        static GetCurrentUserInfo _Value = null;

        static GetCurrentUserInfo()
        {
            ThatType = Type.GetType("Wise.Application.Code.OperatorProvider,Wise.Application.Code");
            if (ThatType == null)
                throw new Exception("无法找到 Wise.Application.Code.OperatorProvider,Wise.Application.Code");
            ProviderProperty = ThatType.GetProperty("Provider", BindingFlags.Static | BindingFlags.Public);
            if (ProviderProperty == null)
                throw new Exception("无法找到 Wise.Application.Code.OperatorProvider.Provider");
            CurrentMethod = ProviderProperty.PropertyType.GetMethod("Current", BindingFlags.Instance | BindingFlags.Public);
            if (CurrentMethod == null)
                throw new Exception("无法找到 Wise.Application.Code.OperatorProvider.Provider.Current");
            GetCurrentUserDelegate = _get;
        }

        static GetCurrentUserInfo _get()
        {
            object obj1 = ProviderProperty.GetValue(null, null);
            Object obj2 = CurrentMethod.Invoke(obj1, new Object[0]);
            return obj2.CloneTo<GetCurrentUserInfo>();
        }

        /// <summary>
        /// 获取当前用户
        /// </summary>
        public static GetCurrentUserInfo Current
        {
            get
            {
                if (_Value == null)
                {
                    _Value = GetCurrentUserDelegate();

                }
                return _Value;
            }
        }

        /// <summary>
        /// 用户主键
        /// </summary>
        public string UserId { get; set; }
        /// <summary>
        /// 用户编号
        /// </summary>
        public string Code { get; set; }
        /// <summary>
        /// 用户姓名
        /// </summary>
        public string UserName { get; set; }
        /// <summary>
        /// 公司Id
        /// </summary>
        public string CompanyId { get; set; }
        /// <summary>
        /// 部门Id
        /// </summary>
        public string DepartmentId { get; set; }
        /// <summary>
        /// 诊所ID
        /// </summary>
        public string DefaultClinicID { get; set; }

        /// <summary>
        /// 货币类型
        /// </summary>
        public string CurrencyType { get; set; }



        /// <summary>
        /// 角色
        /// </summary>
        public string RoleId { get; set; }
    }
}
